#include "types.h"
#include <QtWidgets/qgraphicsscene.h>
#include <cstdio>
#include <qlabel.h>
#include <qregion.h>
#include <qtextdocument.h>
#ifdef _MSWIN_
#include <windows.h>
#endif
// Copyright (C) 2021 The Qt Company Ltd.
// SPDX-License-Identifier: LicenseRef-Qt-Commercial OR GPL-3.0-only

#include "mainwidget.h"
#include "src/datachart.h"
#include <QMessageBox>
#include <QtCharts/QBarSeries>
#include <QtCharts/QChart>
#include <QtCharts/QChartView>
#include <QtCharts/QValueAxis>
#include <QtWidgets/QCheckBox>
#include <QtWidgets/QFormLayout>
#include <QtWidgets/QGridLayout>
#include <QtWidgets/QGroupBox>
#include <QtWidgets/QPushButton>
#include <qgridlayout.h>
#include <qpushbutton.h>
#include <qwidget.h>

extern DataParam g_dp;

void*
make_deal(void*)
{
  // Trade::MoneyTree mt;
  // mt.make_deal(g_sp.td, g_sp.vom, g_sp.g_start_idx, g_sp.epos,
  // g_sp.g_stop_idx);

  return nullptr;
}

QT_USE_NAMESPACE

MainWidget::MainWidget(QWidget* parent)
  : QWidget(parent)
{
  // Create chart view with the chart
  m_chart = new DataChart();
  m_dataView = new DataView(m_chart, this);
  m_dataView->setRenderHint(QPainter::Antialiasing);

  createUi();

  connect(
    m_freqSlider, &QSlider::valueChanged, this, &MainWidget::setFrequence);
  connect(m_btnShow, &QPushButton::clicked, this, &MainWidget::showData);
  connect(m_btnDetail, &QPushButton::clicked, this, &MainWidget::showDetail);
  connect(m_btnRunOrStop, &QPushButton::clicked, this, &MainWidget::run);
  connect(m_btnToggleTom, &QPushButton::clicked, this, &MainWidget::toggleTom);
  connect(
    m_btnToggleJerry, &QPushButton::clicked, this, &MainWidget::toggleJerry);
  connect(
    m_btnToggleMickey, &QPushButton::clicked, this, &MainWidget::toggleMickey);
  connect(m_btnToggleMickeyLines,
          &QPushButton::clicked,
          this,
          &MainWidget::toggleMickeyLines);
  connect(
    m_togglePosIsTime, &QCheckBox::toggled, this, &MainWidget::togglePosIsTime);

  connect(m_chart, &DataChart::mouseMove, this, &MainWidget::mouseMove);
  connect(m_btnLeft_1, &QPushButton::clicked, this, &MainWidget::moveLeft1);
  connect(m_btnLeft_2, &QPushButton::clicked, this, &MainWidget::moveLeft2);
  connect(m_btnLeft_3, &QPushButton::clicked, this, &MainWidget::moveLeft3);
  connect(m_btnRight_1, &QPushButton::clicked, this, &MainWidget::moveRight1);
  connect(m_btnRight_2, &QPushButton::clicked, this, &MainWidget::moveRight2);
  connect(m_btnRight_3, &QPushButton::clicked, this, &MainWidget::moveRight3);
  connect(
    m_btnFuture, &QPushButton::clicked, this, &MainWidget::toggleShowFuture);
  connect(m_dataView->getTable(),
          &QTableWidget::itemDoubleClicked,
          this,
          &MainWidget::set_pos_by_table_item);

  // setWindowFlags(Qt::FramelessWindowHint | Qt::WindowStaysOnTopHint);
  setWindowFlags(Qt::WindowStaysOnTopHint);

  m_dataView->resize(size());

  set_params_data();
  setPosIndex(g_dp.g_start_idx);
  draw_tick_data();
}

MainWidget::~MainWidget() {}

enum row_btn_layout
{
  row_txt_freq_id,
  row_txt_data_pos,
  row_toggle_time,
  row_layout_l_r,
  row_btn_show,
  row_btn_detail,
  row_btn_run_stop,
  row_btn_future,
  row_toggle_pet,
  row_lbl_price,
  row_lbl_data_pos,
  row_lbl_timer,
};

void
MainWidget::createUi() noexcept
{
  // Create buttons for ui
  buttonLayout = new QGridLayout();

  const int init_freq = 50;
  old_frequence = 1;
  const int init_width = 150;

  m_freqSlider = new QSlider(this);
  m_freqSlider->setOrientation(Qt::Horizontal);
  m_freqSlider->setMaximum(2048);
  m_freqSlider->setMinimum(1);
  m_freqSlider->setSliderPosition(init_freq);
  m_freqSlider->setMaximumWidth(init_width);
  g_dp.m_frequence = init_freq;
  buttonLayout->addWidget(m_freqSlider, row_txt_freq_id, 0);

  m_txtDataIdx = new QTextEdit(this);
  m_txtDataIdx->setMaximumWidth(init_width);
  m_txtDataIdx->setMaximumHeight(30);
  m_txtDataIdx->setText(std::to_string(g_dp.g_start_idx).c_str());
  buttonLayout->addWidget(m_txtDataIdx, row_txt_data_pos, 0);

  m_togglePosIsTime = new QCheckBox("pos is time");
  m_togglePosIsTime->setChecked(false);
  buttonLayout->addWidget(m_togglePosIsTime, row_toggle_time, 0);

  layoutLR = new QGridLayout;
  m_btnLeft_1 = new QPushButton("<", this);
  m_btnLeft_2 = new QPushButton("<", this);
  m_btnLeft_3 = new QPushButton("<", this);
  m_btnRight_1 = new QPushButton(">", this);
  m_btnRight_2 = new QPushButton(">", this);
  m_btnRight_3 = new QPushButton(">", this);
  m_btnLeft_3->setMaximumWidth(20);
  m_btnLeft_2->setMaximumWidth(20);
  m_btnLeft_1->setMaximumWidth(20);
  m_btnRight_1->setMaximumWidth(20);
  m_btnRight_2->setMaximumWidth(20);
  m_btnRight_3->setMaximumWidth(20);
  layoutLR->addWidget(m_btnLeft_3, 0, 0);
  layoutLR->addWidget(m_btnLeft_2, 0, 1);
  layoutLR->addWidget(m_btnLeft_1, 0, 2);
  layoutLR->addWidget(m_btnRight_1, 0, 3);
  layoutLR->addWidget(m_btnRight_2, 0, 4);
  layoutLR->addWidget(m_btnRight_3, 0, 5);
  buttonLayout->addLayout(layoutLR, row_layout_l_r, 0);

  m_btnShow = new QPushButton("Show", this);
  buttonLayout->addWidget(m_btnShow, row_btn_show, 0);

  m_btnDetail = new QPushButton("Detail/zoom", this);
  buttonLayout->addWidget(m_btnDetail, row_btn_detail, 0);

  m_btnRunOrStop = new QPushButton("Run or Stop", this);
  buttonLayout->addWidget(m_btnRunOrStop, row_btn_run_stop, 0);

  m_btnFuture = new QPushButton("Future", this);
  buttonLayout->addWidget(m_btnFuture, row_btn_future, 0);

  lotPets = new QGridLayout();
  m_btnToggleTom = new QPushButton("T", this);
  m_btnToggleTom->setMaximumWidth(30);
  lotPets->addWidget(m_btnToggleTom, 0, 0);
  m_btnToggleJerry = new QPushButton("J", this);
  m_btnToggleJerry->setMaximumWidth(30);
  lotPets->addWidget(m_btnToggleJerry, 0, 1);
  m_btnToggleMickey = new QPushButton("M", this);
  m_btnToggleMickey->setMaximumWidth(30);
  lotPets->addWidget(m_btnToggleMickey, 0, 2);
  m_btnToggleMickeyLines = new QPushButton("L", this);
  m_btnToggleMickeyLines->setMaximumWidth(30);
  lotPets->addWidget(m_btnToggleMickeyLines, 0, 3);
  buttonLayout->addLayout(lotPets, row_toggle_pet, 0);

  QPalette palette;
  // palette.setColor(QPalette::Window, Qt::white);
  palette.setColor(QPalette::WindowText, Qt::white);

  m_lblPrice = new QLabel("Price", this);
  m_lblPrice->setAutoFillBackground(true);
  m_lblPrice->setPalette(palette);
  buttonLayout->addWidget(m_lblPrice, row_lbl_price, 0);

  m_lblX = new QLabel("Pos", this);
  m_lblX->setAutoFillBackground(true);
  m_lblX->setPalette(palette);
  buttonLayout->addWidget(m_lblX, row_lbl_data_pos, 0);

  m_lblTimer = new QLabel("TImer", this);
  m_lblTimer->setAutoFillBackground(true);
  m_lblTimer->setPalette(palette);
  buttonLayout->addWidget(m_lblTimer, row_lbl_timer, 0);

  buttonLayout->setRowStretch(row_lbl_timer + 1, 1);

  mainLayout = new QGridLayout();
  mainLayout->addWidget(m_dataView, 0, 0, 3, 1);
  mainLayout->addLayout(buttonLayout, 0, 1);
  setLayout(mainLayout);
}

void
MainWidget::resizeEvent(QResizeEvent* e)
{
  m_dataView->resize(mainLayout->cellRect(0, 0).size());
}

int
MainWidget::draw__() noexcept
{
  if (!g_dp.tick)
    return (-1);

  if (!m_data_changed)
    return (0);

  m_chart->draw();
  m_data_changed = false;
  return (0);
}

int
MainWidget::draw_tick_data() noexcept
{
  stop_animation_();
  return draw__();
}

int
MainWidget::togglePosIsTime(bool checked) noexcept
{
  b_pos_is_tm = checked;
  return (0);
}

int
MainWidget::start_animation_() noexcept
{
  if (!m_run) {
    m_run = true;
    timerId = startTimer(1);
  }

  return (0);
}

int
MainWidget::stop_animation_() noexcept
{
  if (m_run) {
    m_run = false;
    killTimer(timerId);
    timerId = 0;
  }
  return (0);
}

int
MainWidget::run() noexcept
{
  if (!m_run) {
    m_stopPosIndex = (int64_t)(g_dp.tick_size - 1);
    start_animation_();
  } else {
    stop_animation_();
  }
  return (0);
}

void
MainWidget::timerEvent(QTimerEvent* event [[maybe_unused]])
{
  const int delta = (g_dp.m_frequence == 1) ? 100 : 900;
  if (m_run) {
    movePosDelta(delta);
  } else {
    stop_animation_();
    movePosDelta(m_stopPosIndex);
  }
}

void
MainWidget::closeEvent(QCloseEvent*)
{
  stop_animation_();
}

void
MainWidget::showData() noexcept
{
  stop_animation_();

  int64_t pos = m_txtDataIdx->toPlainText().toLongLong();
  g_dp.set_pos(pos);

  if (g_dp.m_frequence == 1) {
    setFrequence(old_frequence);
    old_frequence = 1;
  }

  setPosIndex(g_dp.m_posIndex);
  draw_tick_data();
  show_params__();

  // QString fileName = "file_name.png";
  // QPixmap pixMap = m_chartView->grab(m_chartView->sceneRect().toRect());
  // pixMap.save(fileName);
}

void
MainWidget::showDetail() noexcept
{
  stop_animation_();
  if (old_frequence == 1) {
    old_frequence = g_dp.m_frequence;
    setFrequence(1);
  } else {
    setFrequence(old_frequence);
    old_frequence = 1;
  }
}

void
MainWidget::setPosIndex(const int64_t pos) noexcept
{
  m_data_changed = true;

  m_chart->setTimerSeries(pos);
  m_txtDataIdx->setText(std::to_string(g_dp.m_posIndex).c_str());
  m_lblTimer->setText(m_chart->getTimerString());
  m_lblPrice->setText(std::to_string(g_dp.tick[pos].price).c_str());
  m_lblX->setText(std::to_string(0).c_str());
}

void
MainWidget::setFrequence(const int frequence) noexcept
{
  g_dp.m_frequence = frequence;
  m_chart->setTimerSeries(g_dp.m_posIndex);
  m_data_changed = true;
  draw_tick_data();
}

void
MainWidget::received_pet_dir_time(const int pet_id)
{
  stop_animation_();

  m_chart->setPetTimer(pet_id);
  m_chart->update();
}

void
MainWidget::received_mickey_lines()
{
  stop_animation_();
  m_chart->setMickLines();
  m_chart->updateY();
  m_chart->update();
}

void
MainWidget::received_position(const int64_t pos)
{
  // printf("i received message: %s\n", msg);
  // fflush(stdout);

  stop_animation_();
  if (pos) {
    setPosIndex(pos);
    draw_tick_data();
  }
}

void
MainWidget::mouseMove(const int pos, const price_t hpx) noexcept
{
  m_lblPrice->setText(std::to_string(hpx).c_str());
  m_lblX->setText(std::to_string(pos).c_str());
}

void
MainWidget::moveLeft1() noexcept
{
  movePosDelta(-10);
}

void
MainWidget::moveLeft2() noexcept
{
  movePosDelta(-100);
}

void
MainWidget::moveLeft3() noexcept
{
  movePosDelta(-1000);
}

void
MainWidget::moveRight1() noexcept
{
  movePosDelta(+10);
}

void
MainWidget::moveRight2() noexcept
{
  movePosDelta(+100);
}

void
MainWidget::moveRight3() noexcept
{
  movePosDelta(+1000);
}

void
MainWidget::toggleShowFuture() noexcept
{
  stop_animation_();
  sos.b_shouw_future = !sos.b_shouw_future;
  m_data_changed = true;
  draw_tick_data();
}

void
MainWidget::toggleTom() noexcept
{
  sos.b_show_tom = !sos.b_show_tom;
  m_chart->visibleTom();
  m_chart->update();
}

void
MainWidget::toggleJerry() noexcept
{
  sos.b_show_jerry = !sos.b_show_jerry;
  m_chart->visibleJerry();
  m_chart->update();
}

void
MainWidget::toggleMickey() noexcept
{
  sos.b_show_mickey = !sos.b_show_mickey;
  m_chart->visibleMickey();
  m_chart->update();
}

void
MainWidget::toggleMickeyLines() noexcept
{
  sos.n_show_space_lines++;
  if (sos.n_show_space_lines > 4)
    sos.n_show_space_lines = 0;
  m_chart->visibleMickeyLines();
  m_chart->update();
}

void
MainWidget::moveToPos(const int64_t idx) noexcept
{
  if (!g_dp.set_pos(idx)) {
    setPosIndex(g_dp.m_posIndex);
    draw_tick_data();
  }
}

void
MainWidget::movePosDelta(const int delta) noexcept
{
  if (!g_dp.move_pos_delta(delta)) {
    setPosIndex(g_dp.m_posIndex);
    draw__();
  }
}

void
MainWidget::show_params__() const noexcept
{
  auto vo_ptr = Trade::get_vo_by_index(g_dp.vo, g_dp.vo_size, g_dp.m_posIndex);
  if (vo_ptr) {
    vo_ptr->show_params((time_t)(g_dp.tick[g_dp.m_posIndex].ftime),
                        g_dp.tick[g_dp.m_posIndex].price);
  }
}

void
MainWidget::set_pos_by_table_item(QTableWidgetItem* item)
{
  ActionPtr action = get_action_in_list(item->row());
  if (action && action->idx) {
    m_txtDataIdx->setPlainText(std::to_string(action->idx).c_str());
    showData();
  }
}


void
MainWidget::received_reverse_space()
{
  m_chart->update(m_chart->rect());
  // m_dataView->update(m_dataView->rect());
  // update(rect());
}